/*
 * SQLGrammer.cpp
 *
 *  Created on: Jun 10, 2010
 *      Author: administrator
 */

#include "modules/SQLParser.h"
#include "types/query.h"
using namespace std;

SQLParser::SQLParser() {
	
}

SQLParser::~SQLParser() {
	//delete recmanager;
}

SQL * SQLParser::parse(vector<string, allocator<string> > &statement, Executor *validate){
	SQL *sql = new SQL;
	if(statement[0] == "CREATE" || statement[0] == "create"){
		//cout<<"Create" << endl;
		sql = parseCreate(statement,validate);
	}
	else if(statement[0] == "INSERT" || statement[0] == "insert"){
		//cout<<"Insert" << endl;
		sql = parseInsert(statement,validate);
	}
	else if(statement[0] == "SELECT" || statement[0] == "select"){
		//cout<<"Select" << endl;
		sql = parseSelect(statement,validate);
	}
	else if(statement[0] == "PRINT" || statement[0] == "print"){
		parsePrint(statement);
	}
	else if(statement[0] == "SET" || statement[0] == "set"){
		if(statement[1] == "TIMER" || statement[1] == "timer"){
			if(statement[2] == "ON" || statement[2] == "on")
				Main::timer = true;
			else if(statement[2] == "OFF" || statement[2] == "off")
				Main::timer = false;
			else{
				cout << "Error: set timer command is incorrect." << endl;
			}
		}
		else{
			cout << "Error: set timer command is incorrect." << endl;
		}
	}
	else if(statement[0] == "COMMIT" || statement[0] == "commit"){
		RecordManager recmanager = RecordManager();
		recmanager.commit();
	}
	else{
		cout<<"Error: input correct command, " << "'"<< statement[0] << "'" << " not found." << endl;
	}
	return sql;
}

SQL * SQLParser::parseCreate(vector<string, allocator<string> > &statement, Executor *validate){
	int size = statement.size();
	SQL *sql = new SQL("CREATE");
	sql->num_attr = 0;
	if(size > 5){
		if(statement[1] == "TABLE" || statement[1] == "table"){

			sql->table_name = statement[2];
			if(statement[3] == "(")
			{
				if(statement[4] == "" && statement[5] == ")")
				{
					cout << "Error: enter the attributes." << endl;
					return sql;
				}

				for(int i=4;statement[i] != ")";i++){
					if(statement[i] == " ")
						continue;
					sql->attributes.push_back(statement[i]);
					for(int j=0; j<sql->num_attr; j++){
						if(sql->attributes[j] == sql->attributes[sql->num_attr])
						{
							cout<<"Error: attribute name is not unique." << endl;
							return sql;
						}
					}
					sql->num_attr++;
				}
			}
			else
			{
				cout << "Error: expecting '(' after table name but found " << "'" << statement[3] <<"'." << endl;
				return sql;
			}
		}
		else{
			cout << "Error: expecting 'TABLE' or 'table' but found " << statement[1] << " after " << statement[0] << endl;
			return sql;
		}
	}
	else{
		cout << "Error: input correct command." << endl;
		return sql;
	}
	if(sql->table_name.size()>3){
		cout<<"Error: table name has more than 3 characters."<<endl;
		return sql;
	}
	for(int i=0; i < sql->num_attr; i++){
		if(sql->attributes[i].size() > 3)
			cout<<"Error: attribute " << sql->attributes[i] <<" name has more than 3 characters."<<endl;
	}
	if(validate->validateCreate(sql)){
		//cout<<"Call create To be done" << endl;
		RecordManager recmanager = RecordManager();
		recmanager.create_table(sql->table_name,sql->num_attr);
	}
	return sql;
}

SQL * SQLParser::parseInsert(vector<string, allocator<string> > &statement,Executor *validate){
	int size = statement.size();
	SQL *sql = new SQL("INSERT");
	sql->num_values = 0;
	if(size > 6){
		if(statement[1] == "INTO" || statement[1] == "into"){
			sql->table_name = statement[2];
			if(statement[3] == "VALUES" || statement[3] == "values"){
				if(statement[4] == "(")
				{
					if(statement[5] == "" && statement[6] == ")")
					{
						cout << "Error: enter the attribute values." << endl;
						return sql;
					}
					for(int i=5;statement[i] != ")";i++){
						if(statement[i] == " ")
							continue;
						sql->attr_values.push_back(atoi(statement[i].c_str()));
						sql->num_values++;
					}
				}
				else
				{
					cout << "Error: expecting '(' after table name but found " << "'" << statement[4] <<"'." << endl;
					return sql;
				}
			}
			else{
				cout << "Error: expecting 'VALUES' or 'values' but found " << statement[3] << " after " << statement[2] << endl;
				return sql;
			}
		}
		else{
			cout << "Error: expecting 'INTO' or 'into' but found " << statement[1] << " after " << statement[0] << endl;
			return sql;
		}
	}
	else{
		cout << "Error: input correct command." << endl;
		return sql;
	}
	
	if(validate->validateInsert(sql)){
		//cout<<"Call insert To be done" << endl;
		RecordManager recmanager;
		//Record rec = Record(sql->attr_values);
		recmanager.add_record(sql->table_name,sql->attr_values);
	}
	return sql;
}

SQL * SQLParser::parseSelect(vector<string, allocator<string> > &statement,Executor *validate){
	int size = statement.size();
	bool correctCondition = false;
	SQL *sql = new SQL("SELECT");
	sql->num_attr = 0;
	if(size > 3){
		if(statement[1] == "*" ){
			if(statement[2] == "FROM" || statement[2] == "from"){
				sql->table_name = statement[3];
				if(size > 4){
					if(statement[4] == "WHERE" || statement[4] == "where"){
						vector<string>::iterator it = statement.begin();
						advance(it,5);
						int i =6;
						if(it >= statement.end()){
							cout << "Error: command is not correct, give the condition." << endl;
							return sql;
						}
						while(it < statement.end()){
							if(i<size && statement[i] == "="){
								if(i != size)
									sql->conditions[statement[i-1]] = statement[i+1];
								else{
									cout << "Error: command is not correct, give the correct condition." << endl;
									return sql;
								}
								correctCondition = true;
							}
							else if(!correctCondition){
								cout << "Error: command is not correct, give the correct condition." << endl;
								return sql;
							}
							if(i<size && (statement[i] == "AND"  || statement[i] == "and"))
								sql->andCondition = true;
							if(i<size && (statement[i] == "OR"  || statement[i] == "or"))
								sql->orCondition = true;
							i = i+2;
							it = it + 2;
						}
					}
					else{
						cout << "Error: expecting 'where' but found " << statement[4] << endl;
						return sql;
					}
				}
			}
			else{
				cout << "Error: expecting 'from' but found " << statement[2] << endl;
				return sql;
			}
		}
		else {
			int i = 1;
			while(i<size){
				if(statement[i] == ",")
					continue;
				if(statement[i] == "FROM" || statement[i] == "from"){
					i++;
					break;
				}
				sql->attributes.push_back(statement[i]);
				sql->num_attr++;
				i++;
			}
			if(statement[i-1] == "FROM" || statement[i-1] == "from"){
				if(i <= size)
					sql->table_name = statement[i];
				else{
					cout << "Error: command is not correct" << endl;
					return sql;
				}
				i++;
				if(i < size){
					if(statement[i] == "WHERE" || statement[i] == "where"){
						vector<string>::iterator it = statement.begin();
						advance(it,5);
						int j = i + 2;
						if(it >= statement.end()){
							cout << "Error: command is not correct, give the condition." << endl;
							return sql;
						}
						while(it < statement.end()){
							if(j<size && statement[j] == "="){
								if(j != size)
									sql->conditions[statement[j-1]] = statement[j+1];
								else{
									cout << "Error: command is not correct, give the correct condition." << endl;
									return sql;
								}
								correctCondition = true;
							}
							else if(!correctCondition){
								cout << "Error: command is not correct, give the correct condition." << endl;
								return sql;
							}
							if(j<size && (statement[j] == "AND" || statement[j] == "and"))
								sql->andCondition = true;
							j = j+2;
							it = it + 2;
						}
					}
					else{
						cout << "Error: expecting 'where' but found " << statement[i] << endl;
						return sql;
					}
				}
			}
			else
			{
				cout << "Error: expecting 'from' but found " << statement[i-1] << endl;
				return sql;
			}
		}
	}
	else{
		cout << "Error: input correct command." << endl;
		return sql;
	}

	validate->validateSelect(sql);	

	return sql;
}

void SQLParser::parsePrint(vector<string, allocator<string> > &statement){
	if(statement[1] == "CATALOG" || statement[1] == "catalog"){
		Executor ex = Executor();
		ex.printCatalog();
	}
	else if(statement[1] == "BUFFER" || statement[1] == "buffer"){
		//cout << "Print Buffer to be done." << endl;
		RecordManager recmanager = RecordManager();
		string what = "PRINT BUFFER";
		recmanager.print(what);
	}
	else if(statement[1] == "HIT" || statement[1] == "hit"){
		if(statement[2] == "RATE" || statement[2] == "rate"){
			//cout << "Print Hit rate to be done." << endl;
			RecordManager recmanager = RecordManager();
			string what = "PRINT HIT RATE";
			recmanager.print(what);
		}
		else
		{
			cout << "Error: print command is not correct." << endl;
			return;
		}
	}
	else
	{
		cout << "Error: print command is not correct." << endl;
	}
}
